//
//  ViewController.m
//  GCDSample
//
//  Created by LuckyStrike on 2020/11/16.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
        NSLog(@"begin");
//        [self asynMethod];
//        [self barric];
    [self semaphoreSync];
        NSLog(@"end");
}
/**
 * semaphore 线程同步
 */
- (void)semaphoreSync {
    
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"semaphore---begin");
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    __block int number = 0;
    dispatch_async(queue, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        
        number = 100;
        
        dispatch_semaphore_signal(semaphore);
    });
    
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"semaphore---end,number = %zd",number);
}
/**
 * 队列组 dispatch_group_enter、dispatch_group_leave
 */
- (void)groupEnterAndLeave {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程

        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步操作都执行完毕后，回到主线程.
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    
        NSLog(@"group---end");
    });
}
/**
 * 队列组 dispatch_group_wait
 */
- (void)groupWait {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
    NSLog(@"group---begin");
    
    dispatch_group_t group =  dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 追加任务 1
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 追加任务 2
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
    });
    
    // 等待上面的任务全部完成后，会往下继续执行（会阻塞当前线程）
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    NSLog(@"group---end");
    
}
/**
 * 队列组 dispatch_group_notify
 */
- (void)groupNotify {
    dispatch_group_t group =  dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_async(group, queue, ^{
        // 追加任务 1
        [[self class] sleepWithRangeTime:1 and:5 log:@"1"];
    });
    
    dispatch_group_async(group, queue, ^{
        // 追加任务 2
        [[self class] sleepWithRangeTime:1 and:5 log:@"2"];
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步任务 1、任务 2 都执行完毕后，回到主线程执行下边任务
        NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    });
}

- (void)barric{
//    异步并行队列，执行两组操作，而且第一组操作执行完之后，才能开始执行第二组操作
    dispatch_queue_t queue = dispatch_queue_create("some", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        [[self class] sleepWithRangeTime:1 and:5 log:@"1"];
    });
    dispatch_async(queue, ^{
        [[self class] sleepWithRangeTime:1 and:5 log:@"2"];
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"栅栏");
    });
    dispatch_async(queue, ^{
        [[self class] sleepWithRangeTime:1 and:5 log:@"3"];
    });
    dispatch_async(queue, ^{
        [[self class] sleepWithRangeTime:1 and:5 log:@"4"];
    });
}

- (void)asynMethod{
    //    异步并行队列    无序返回
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (int i = 0 ; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%d-async",i);
            [[self class] sleepWithRangeTime:1.0 and:5.0 log:[NSString stringWithFormat:@"%d",i]];
        });
    }
}

#pragma mark <sleep method>
+ (void)sleepWithTime:(CGFloat)delayTime log:(NSString*)log{
    [NSThread sleepForTimeInterval:delayTime];
    NSLog(@"%@-%f",log,delayTime);
}
+ (void)sleepWithRangeTime:(CGFloat)minTime and:(CGFloat)maxTime log:(NSString*)log{
    CGFloat time = minTime + arc4random() % (int)(maxTime * 10 - minTime * 10) / 10.0f;
    [NSThread sleepForTimeInterval:time];
    NSLog(@"%@-%f:%@",log,time,[NSThread currentThread]);
}

@end
